<?php
/**
 * Middleweare between mysql databases and rail. Provide a basic interface to mysql and a login method for rail.
 * Get simple informations about connected rail, like actual connected user or rail root_container.
 *
 * PHP versions 5
 *
 * Copyright (C)
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of ERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
 * Fundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
 *
 * Copyright (C)
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of ERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
 * Fundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
 *
 * @author Bastian Schröder <bs@chemanet.de>
 * @version 2007-02-10
 * @package rail
 */

// includes
require_once( "rail_types.conf.php" );
require_once( "rail_mimetypes.conf.php" );

// define some global values
define("PHPrail_VERSION", "1.0");

/**
 * rail autoload function.
 *
 * @param string pClassname
 * @return void
 */
function __autoload( $pClassname ){
	// need an exception class
	if( strrpos( $pClassname, "_exception" ) )
		require_once( "exceptions/" . $pClassname . ".class.php" );
	// default case
	else
		require_once( $pClassname . ".class.php" );
}

class rail_connector{

	/**
	 * Connector to mysql databases.
	 *
	 * @var mysqli
	 */
	private $mysqli;

	/**
	 * Current logedin rail_user.
	 *
	 * @var rail_user
	 */
	private $rail_user;

	/**
	 * rail_root for this databases.
	 *
	 * @var rail_root
	 */
	private $rail_root;

	/**
	 * Count number of database requests.
	 * Debug reason.
	 *
	 * @var rail_root
	 */
	private $request_counter = 0;


	/**
	 * Initialization of rail_connector.
	 * Connect to mysql server, select databases for rail and login.
	 * By default 'guest' user is loged into rail.
	 *
	 * @exception rail_exception
	 * @param string $pDatabase mysql databases
	 * @param string $pUser mysql user
	 * @param string $pPasswd mysql passwd
	 * @param string $pServer mysql server, default is localhost
	 */
	public function __construct ( $pDatabase, $pUser, $pPasswd, $pServer = "localhost" ) {
		// connect to mysql server
		$this->mysqli = new mysqli( $pServer, $pUser, $pPasswd );
		if ( mysqli_connect_errno() )
			throw new rail_exception( null, mysqli_connect_error() );

		// select table
		$this->mysqli->select_db( $pDatabase );
		if ( $this->mysqli->errno )
			throw new rail_exception( null, "Can't find databases: '$pDatabase'" );

		// hard login guest user. get user with username guest and the lowesed rail_id.
		$guest_id = $this->send_request(
			"SELECT
				objects.id
			 FROM
			 	objects,objects_attributes
			 WHERE
			 	objects.id = objects_attributes.object AND objects.`type`='RAIL_USER' AND
				objects_attributes.`attribute` = 'OBJ_NAME' AND objects_attributes.`value` = 'guest'
			ORDER BY
				`id` DESC
			LIMIT 1"
		)->fetch_assoc();
		$this->rail_user = rail_factory::get_object( $this, $guest_id["id"] );

		// get rail_root
		$root_id = $this->send_request( "SELECT id FROM objects WHERE `environment`='0' AND `type`='RAIL_ROOT' LIMIT 1" )->fetch_assoc();
		$this->rail_root = rail_factory::get_object( $this, $root_id["id"] );
	}


	/**
	 * Disconnected from rail.
	 *
	 */
	public function disconnect () {
		$this->mysqli->close();
		unset( $this->mysqli );
		unset( $this->rail_user );
		unset( $this->rail_root );
	}


	/**
	 * Get number of databases requests.
	 *
	 * @return int
	 */
	public function get_request_count () {
		return $this->request_counter;
	}


	/**
	 * Return rail_root for this databases.
	 *
	 * @return rail_root
	 */
	public function get_root () {
		return $this->rail_root;
	}


	/**
	 * Get current loged in rail_user.
	 *
	 * @return rail_user
	 */
	public function get_user () {
		return $this->rail_user;
	}


	/**
	 * Connect a new user to rail. If login failed, nothing change.
	 *
	 * @exception rail_exception
	 * @param  rail_user $pUser
	 * @param string $pPasswd
	 */
	public function login( $pUser, $pPasswd ) {
		$data = $this->send_request( "
			SELECT
				objects.id
			 FROM
			 	objects,objects_attributes
			 WHERE
			 	objects.id = objects_attributes.`object` AND
			 	objects.`type` ='rail_user' AND
			 	objects_attributes.`attribute` = 'OBJ_NAME' AND objects_attributes.`value` = '". trim( $pUser ) . "'
			 LIMIT 1
		" )->fetch_assoc();
		$user_id = $data[ "id" ];

		// get passwd
		$data = $this->send_request( "SELECT `value` FROM objects_attributes WHERE `object`='$user_id' AND attribute='RAIL_PASSWD'  LIMIT 1" )->fetch_assoc();
		$user_passwd = $data[ "value" ];

		// throw exceptions if user with this passwd dosn't exist.
		if( $user_id < 1 || $user_passwd != md5( $pPasswd ) )
			throw new rail_exception( null, "Access denied: password or user failure!" );

		$this->rail_user = rail_factory::get_object( $this, $user_id );
	}


	/**
	 * Send an mysql query to databases and return result.
	 * Try to detect a mysql injection and increment request counter.
	 * This Method is public but it's a bad idear to call it from outside a rail class.
	 *
	 * @exception rail_exception
	 * @param string $pQuery mysql query
	 * @return mysql_result
	 */
	public function send_request( $pQuery ){
		// detect sql injection

		// get mysqli query result
		$query = $this->mysqli->query( $pQuery );
		if ( mysqli_errno($this->mysqli) )
			throw new rail_exception( null, mysqli_error($this->mysqli) );

		// debug counter
		$this->request_counter ++ ;

		return $query;
	}

} // End of rail_connector
?>